<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Text in PyCairo</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="PyCairo, graphics, Python, 2D vector library, text">
<meta name="description" content="This chapter of the PyCairo tutorial covers text.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container2">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content2">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Text in PyCairo</h1>


<p>
In this part of the PyCairo tutorial, we will work with text.
</p>

<div class="big_hor">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* big_horizontal */
google_ad_slot = "2904953388";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<h2>Soulmate</h2>

<p>
In the first example, we will display some lyrics on a window.
</p>

<pre class="code">
def on_draw(self, wid, cr):

    cr.set_source_rgb(0.1, 0.1, 0.1)
        
    cr.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL, 
        cairo.FONT_WEIGHT_NORMAL)
    cr.set_font_size(13)
    
    cr.move_to(20, 30)
    cr.show_text("Most relationships seem so transitory")
    cr.move_to(20, 60)
    cr.show_text("They're all good but not the permanent one")
    cr.move_to(20, 120)
    cr.show_text("Who doesn't long for someone to hold")
    cr.move_to(20, 150)
    cr.show_text("Who knows how to love without being told")
    cr.move_to(20, 180)
    cr.show_text("Somebody tell me why I'm on my own")
    cr.move_to(20, 210)
    cr.show_text("If there's a soulmate for everyone")
</pre>

<p>
In this code, we display part of the lyrics from the Natasha 
Bedingfields Soulmate song.
</p>

<pre class="explanation">
cr.select_font_face("Purisa", cairo.FONT_SLANT_NORMAL, 
    cairo.FONT_WEIGHT_NORMAL)
</pre>

<p>
Here we select the font face. The method takes three parameters, the 
font family, font slant and the font weight.
</p>

<pre class="explanation">
cr.set_font_size(13)
</pre>

<p>
Here we specify the font size.
</p>

<pre class="explanation">
cr.move_to(20, 30)
cr.show_text("Most relationships seem so transitory")
</pre>

<p>
We display the text on the window by specifying the position of the text and 
calling the <code>show_text()</code> method.
</p>

<img src="/img/gfx/pycairo/soulmate.png" alt="Soulmate">
<div class="figure">Figure: Soulmate</div>


<h2>Centered text</h2>

<p>
Next we will show, how to center text on the window.
</p>

<pre class="code">
def on_draw(self, wid, cr):

    w, h = self.get_size()
        
    cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, 
        cairo.FONT_WEIGHT_BOLD)
    cr.set_font_size(60)
    
    (x, y, width, height, dx, dy) = cr.text_extents("ZetCode")

    cr.move_to(w/2 - width/2, h/2)    
    cr.show_text("ZetCode")
</pre>

<p>
The code will center a text on the window. It remains centered, even
if we resize the window.
</p>

<pre class="explanation">
w, h = self.get_size() 
</pre>

<p>
To center a text on the window, it is necessary to get the size of
the client area of the window.
</p>

<pre class="explanation">
cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL, 
    cairo.FONT_WEIGHT_BOLD)
cr.set_font_size(60)
</pre>

<p>
We select a font and its size to be displayed. 
</p>

<pre class="explanation">
(x, y, width, height, dx, dy) = cr.text_extents("ZetCode") 
</pre>

<p>
We get the text extents. These are some numbers that describe
the text. We need the width of the text for our example.
</p>

<pre class="explanation">
cr.move_to(w/2 - width/2, h/2)    
cr.show_text("ZetCode")
</pre>

<p>
We position the text into the middle of the window and
show it using the <code>show_text()</code> method.
</p>

<img src="/img/gfx/pycairo/centeredtext.png" alt="Centered text">
<div class="figure">Figure: Centered text</div>


<h2>Shaded text</h2>

<p>
Now we will create a shaded text on the window. 
</p>

<pre class="code">
def on_draw(self, wid, cr):
            
    cr.select_font_face("Serif", cairo.FONT_SLANT_NORMAL, 
        cairo.FONT_WEIGHT_BOLD)
    cr.set_font_size(50)
    
    cr.set_source_rgb(0, 0, 0)
    cr.move_to(40, 60)
    cr.show_text("ZetCode")
    
    cr.set_source_rgb(0.5, 0.5, 0.5)
    cr.move_to(43, 63)
    cr.show_text("ZetCode")
</pre>

<p>
To create a shade, we draw the text twice. In different 
colours. The second text is moved a bit to the right and
bottom. 
</p>

<pre class="explanation">
cr.set_source_rgb(0, 0, 0)
cr.move_to(40, 60)
cr.show_text("ZetCode")
</pre>

<p>
The first text is drawn in black ink. It serves as a shade.
</p>

<pre class="explanation">
cr.set_source_rgb(0.5, 0.5, 0.5)
cr.move_to(43, 63)
cr.show_text("ZetCode")
</pre>

<p>
The second text is drawn in some gray ink. It is moved by 3px to 
the right and to the bottom.
</p>

<img src="/img/gfx/pycairo/shade.png" alt="Shaded text">
<div class="figure">Figure: Shaded text</div>


<h2>Text filled with gradient</h2>

<p>
The following example will create a nice effect. We will
fill a text with some linear gradient.
</p>

<pre class="code">
def on_draw(self, wid, cr):
                
    cr.set_source_rgb(0.2, 0.2, 0.2)
    cr.paint()
    
    h = 90
    
    cr.select_font_face("Serif", cairo.FONT_SLANT_ITALIC, 
        cairo.FONT_WEIGHT_BOLD)
    cr.set_font_size(h)
    
    lg = cairo.LinearGradient(0, 15, 0, h*0.8)
    lg.set_extend(cairo.EXTEND_REPEAT)
    lg.add_color_stop_rgb(0.0, 1, 0.6, 0)
    lg.add_color_stop_rgb(0.5, 1, 0.3, 0) 
                    
    cr.move_to(15, 80)
    cr.text_path("ZetCode")
    cr.set_source(lg)
    cr.fill()
</pre>

<p>
We draw a text on the window filled with a linear gradient.
The colours are some orange colours.
</p>

<pre class="explanation">
cr.set_source_rgb(0.2, 0.2, 0.2)
cr.paint() 
</pre>

<p>
To make it more visually appealing, we paint the background in 
dark gray colour.
</p>

<pre class="explanation">
lg = cairo.LinearGradient(0, 15, 0, h*0.8)
lg.set_extend(cairo.EXTEND_REPEAT)
lg.add_color_stop_rgb(0.0, 1, 0.6, 0)
lg.add_color_stop_rgb(0.5, 1, 0.3, 0) 
</pre>

<p>
The linear gradient is created. 
</p>

<pre class="explanation">
cr.move_to(15, 80)
cr.text_path("ZetCode")
cr.set_source(lg)
cr.fill() 
</pre>

<p>
The text is displayed on the window. We use the gradient
as a source for painting.
</p>

<img src="/img/gfx/pycairo/textgrad.png" alt="Text filled with gradient">
<div class="figure">Figure: Text filled with gradient</div>


<h2>Letter by letter</h2>

<p>
In this effect, we will display a text letter by letter. The letters will 
be drawn with some delay. 
</p>

<pre class="code">
#!/usr/bin/python

'''
ZetCode PyCairo tutorial 

This program shows text letter by
letter. 

author: Jan Bodnar
website: zetcode.com 
last edited: August 2012
'''

from gi.repository import Gtk, GLib
import cairo


class cv(object):
    
    SPEED = 800
    TEXT_SIZE = 35
    COUNT_MAX = 8


class Example(Gtk.Window):

    def __init__(self):
        super(Example, self).__init__()
        
        self.init_ui()
        self.init_vars()
        
        
    def init_ui(self):    

        self.darea = Gtk.DrawingArea()
        self.darea.connect("draw", self.on_draw)
        self.add(self.darea)
        
        
        GLib.timeout_add(cv.SPEED, self.on_timer)

        self.set_title("Letter by letter")
        self.resize(350, 200)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()
        
        
    def init_vars(self):
        
        self.timer = True
        self.count = 0
        self.text = [ "Z", "e", "t", "C", "o", "d", "e" ]
        

    def on_timer(self):
              
        if not self.timer: return False
    
        self.darea.queue_draw()
        return True        
                        
        
    def on_draw(self, wid, cr):

        cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL,
            cairo.FONT_WEIGHT_BOLD)

        cr.set_font_size(cv.TEXT_SIZE)

        dis = 0

        for i in range(self.count):
            
            (x, y, width, height, dx, dy) = cr.text_extents(self.text[i])
            
            dis += width + 2
            cr.move_to(dis + 30, 50)
            cr.show_text(self.text[i])  
        

        self.count += 1

        if self.count == cv.COUNT_MAX:
            self.timer = False
            self.count = 0
            
        
    
def main():
    
    app = Example()
    Gtk.main()
        
        
if __name__ == "__main__":    
    main()
</pre>

<p>
In our example, we will draw the "ZetCode" string on the GTK window 
letter by letter with some delay.
</p>

<pre class="explanation">
self.text = [ "Z", "e", "t", "C", "o", "d", "e" ]
</pre>

<p>
This is a list of letters to be displayed on the window.
</p>

<pre class="explanation">
cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL,
    cairo.FONT_WEIGHT_BOLD)
</pre>

<p>
We select a Courier font face in bold weight.
</p>

<pre class="explanation">
for i in range(self.count):
    
    (x, y, width, height, dx, dy) = cr.text_extents(self.text[i])
    
    dis += width + 2
    cr.move_to(dis + 30, 50)
    cr.show_text(self.text[i])  
</pre>

<p>
Here we draw the text letter by letter. We get the width
of each of the letters and compute the disptance on the x axis.
</p>


<h2>Glyphs</h2>

<p>
The <code>show_text()</code> method is only suitable for simple text
rendering. Cairo developers call it a toy method. More professional text
rendering is done with glyphs. A <b>glyph</b> is a graphic symbol which
provides a form for a character. A character provides a meaning. It can 
have multiple glyphs. A character has no intrinsic appearance. 
A glyph has no intrinsic meaning.
</p>

<p>
Note that many common programming requirements conserning text are
addressed by the Pango library.
</p>

<pre class="code">
def on_draw(self, wid, cr):
    
    cr.select_font_face("Serif", cairo.FONT_SLANT_NORMAL,
        cairo.FONT_WEIGHT_NORMAL)

    cr.set_font_size(13)

    glyphs = []
    index = 0
    
    for y in range(20):
        for x in range(35):
            glyphs.append((index, x*15 + 20, y*18 + 20))
            index += 1

    cr.show_glyphs(glyphs) 
</pre>

<p>
This code shows 700 glyphs of a chosen font. 
</p>

<pre class="explanation">
glyphs = [] 
</pre>

<p>
The glyphs list will store three integer values. 
The first value is the index of the glyph to the chosen 
font type. The second and the third values are x, y 
positions of a glyph.
</p>

<pre class="explanation">
cr.show_glyphs(glyphs) 
</pre>

<p>
The <code>show_glyphs()</code> method shows the glyphs
on the window.
</p>

<img src="/img/gfx/pycairo/glyphs.png" alt="Glyphs">
<div class="figure">Figure: Glyphs</div>


<p>
This chapter covered text in PyCairo.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified August 30, 2012 <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

